All files / web/src/app/api/curriculum/[playerId]/attachments/[attachmentId]/unapprove route.ts

0% Statements 0/109
0% Branches 0/1
0% Functions 0/1
0% Lines 0/109

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110                                                                                                                                                                                                                           
/**
 * API route for unapproving/reverting a processed worksheet
 *
 * POST /api/curriculum/[playerId]/attachments/[attachmentId]/unapprove
 *   - Removes the problems from the session
 *   - Reverts the attachment to 'needs_review' state
 *   - Useful for testing and correcting mistakes
 */

import { NextResponse } from 'next/server'
import { eq } from 'drizzle-orm'
import { db } from '@/db'
import { practiceAttachments } from '@/db/schema/practice-attachments'
import { sessionPlans, type SlotResult } from '@/db/schema/session-plans'
import { withAuth } from '@/lib/auth/withAuth'
import { canPerformAction } from '@/lib/classroom'
import { getUserId } from '@/lib/viewer'

/**
 * POST - Unapprove/revert a processed worksheet
 */
export const POST = withAuth(async (_request, { params }) => {
  try {
    const { playerId, attachmentId } = (await params) as { playerId: string; attachmentId: string }

    if (!playerId || !attachmentId) {
      return NextResponse.json({ error: 'Player ID and Attachment ID required' }, { status: 400 })
    }

    // Authorization check
    const userId = await getUserId()
    const canModify = await canPerformAction(userId, playerId, 'start-session')
    if (!canModify) {
      return NextResponse.json({ error: 'Not authorized' }, { status: 403 })
    }

    // Get attachment record
    const attachment = await db
      .select()
      .from(practiceAttachments)
      .where(eq(practiceAttachments.id, attachmentId))
      .get()

    if (!attachment) {
      return NextResponse.json({ error: 'Attachment not found' }, { status: 404 })
    }

    if (attachment.playerId !== playerId) {
      return NextResponse.json({ error: 'Attachment not found' }, { status: 404 })
    }

    // Check if it's actually been processed
    if (!attachment.sessionCreated) {
      return NextResponse.json({ error: 'Worksheet has not been approved yet' }, { status: 400 })
    }

    // Get the session to remove problems from
    const sessionId = attachment.createdSessionId || attachment.sessionId
    const session = await db.select().from(sessionPlans).where(eq(sessionPlans.id, sessionId)).get()

    if (!session) {
      return NextResponse.json({ error: 'Associated session not found' }, { status: 404 })
    }

    // Count how many problems came from this attachment
    // We need to figure out which results to remove
    // Since we don't track which results came from which attachment,
    // we'll remove the last N results where N = number of problems in parsing result
    const parsingResult = attachment.approvedResult ?? attachment.rawParsingResult
    const problemCount = parsingResult?.problems?.length ?? 0

    if (problemCount > 0) {
      const existingResults = (session.results ?? []) as SlotResult[]

      // Remove the last N results (assumes they were added by this attachment)
      const newResults = existingResults.slice(0, -problemCount)

      // Update session
      await db
        .update(sessionPlans)
        .set({
          results: newResults,
          // If no results left, mark as in_progress
          status: newResults.length === 0 ? 'in_progress' : 'completed',
        })
        .where(eq(sessionPlans.id, sessionId))
    }

    // Revert attachment to needs_review state
    await db
      .update(practiceAttachments)
      .set({
        parsingStatus: 'needs_review',
        sessionCreated: false,
        createdSessionId: null,
        // Keep the parsing results and review progress intact
      })
      .where(eq(practiceAttachments.id, attachmentId))

    return NextResponse.json({
      success: true,
      message: `Reverted worksheet. Removed ${problemCount} problems from session.`,
      problemsRemoved: problemCount,
    })
  } catch (error) {
    console.error('Error unapproving worksheet:', error)
    return NextResponse.json({ error: 'Failed to unapprove worksheet' }, { status: 500 })
  }
})